package com.dongman.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dongman.mapper.NovelDao;
import com.dongman.model.Chapter;
import com.dongman.model.ChapterPic;
import com.dongman.model.Constants;
import com.dongman.model.Novel;
import com.dongman.scrapy.CrawOneLink;
import com.dongman.scrapy.CrawAllLink;
import com.dongman.scrapy.CrawlUtil;
import com.dongman.service.ManhuaSpiderService;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 爬取漫画的service
 */
@Service
public class ManhuaSpiderServiceImpl implements ManhuaSpiderService {

    @Autowired
    private NovelDao novelDao;

    @Value("${manhua.username}")
    private String username;

    @Value("${manhua.password}")
    private String password;

    @Value("${manhua.cookie}")
    private String cookie;

    @Value("${manhua.picSavePath}")
    private String picSavePath;

    private final static ExecutorService executor = Executors.newFixedThreadPool(5);

    /**
     * 爬取所有的漫画链接,存储漫画的基本信息和章节信息
     * @return
     */
    @Override
    public List<String> crawlAllManhuLinks() {
        List<String> allManHuaLinks = CrawAllLink.getAllLinksByUrl(Constants.all_link);

        for (int i = 0; i < allManHuaLinks.size(); i++) {
            String manhuaLink = allManHuaLinks.get(i);
            System.out.print("开始爬取小说：" + manhuaLink);
            insertOrUpdateOneNovel(manhuaLink);
        }
        return allManHuaLinks;
    }

    /**
     * 单独开启线程，爬取图片
     * @return
     */
    @Override
    public List<ChapterPic> crawAllPicsToLocal() {
        ChapterPic chapterPic1 = new ChapterPic();
        chapterPic1.setIsDownToLocal(Constants.NoDownToLocal);
        //查出需要下载章节的所有的id
        List<JSONObject> chapterIds = novelDao.selectNeedToDwonChapters(chapterPic1);

        for (JSONObject jsonObject : chapterIds) {

            String chapterId = jsonObject.getString("id");
            String novelName = jsonObject.getString("name");
            String chapterName = jsonObject.getString("chapterName");

            ChapterPic chapterPic = new ChapterPic();
            chapterPic.setIsDownToLocal(Constants.NoDownToLocal);
            chapterPic.setChapterId(chapterId);
            List<ChapterPic> chapterPicList = novelDao.selectNotDownPics(chapterPic);

            if (chapterPicList.size() > 0) {
                executor.submit(() -> {
                    CrawlUtil.savePicToBase(novelName, chapterName, chapterPicList, picSavePath, novelDao);
                });
            }
        }
        return null;
    }

    /**
     * 根据章节连接爬取每个章节对应的图片到数据库和本地
     * /漫画名字/章节名字/图片
     * @param
     * @return
     */
    @Override
    public List<ChapterPic> crawlAllPicsByChapterLink(String novelId) {

        Novel n = new Novel();
        n.setId(novelId);
        List<Novel> novels = selectNovelChapterAdnPics(n);

        for (int i = 0; i < novels.size(); i++) {
            Novel novel = novels.get(i);
            System.out.print("parse dongman..." + novel.getLink());
            String novelName = novel.getName();
            System.out.print("dongman name..." + novelName);
            for (Chapter chapter : novel.getChapter()) {
                String chapterName = chapter.getChapterName();
                String chapterId = chapter.getId();
                System.out.print("chapterName..." + chapterName);
                String chapterLink = chapter.getChapterUrl();
                System.out.print("parse chapter..." + chapterLink);
                //从数据库中查找章节对应的图片，如果存在的话就不必插入了
                ChapterPic c = new ChapterPic();
                c.setChapterId(chapterId);
                List<ChapterPic> chapterPicss = novelDao.selectPicsByChapterId(c);
                if (chapterPicss.size() > 0) {
                    System.out.print("chapterName..." + chapterName + "，already down break");
                    continue;
                }

                //不存在继续爬取然后添加进数据库
                List<ChapterPic> chapterPics = CrawOneLink.getAllPicsByLink(chapterLink,
                        cookie, username, password);

                //将图片批量存入数据库
                novelDao.insertChapterPicBatch(chapterPics);

                //将图片按照顺序保存至本地
                //CrawlUtil.savePicToBase(novelName, chapterName, chapterPics, picSavePath, novelDao);
            }
        }

        return null;
    }
    /**
     * 根据章节连接爬取每个章节对应的图片到数据库和本地
     * /漫画名字/章节名字/图片
     * @param
     * @return
     */
    @Override
    public List<ChapterPic> crawlPicssByChapterLink(List<Novel> novels) {
        for (int i = 0; i < novels.size(); i++) {
            Novel novel = novels.get(i);
            String novelName = novel.getName();
            System.out.print("开始下载图片...");
            System.out.print("动漫名字..." + novelName);
            for (Chapter chapter : novel.getChapter()) {
                String chapterName = chapter.getChapterName();
                String chapterId = chapter.getId();
                System.out.print("章节名字..." + chapterName);
                String chapterLink = chapter.getChapterUrl();

                //从数据库中查找章节对应的图片，如果存在的话就不必插入了
                ChapterPic c = new ChapterPic();
                c.setChapterId(chapterId);
                List<ChapterPic> chapterPicss = novelDao.selectPicsByChapterId(c);
                if (chapterPicss.size() > 0) {
                    System.out.print("章节名字..." + chapterName + "，图片已经下载");
                    continue;
                }

                //不存在继续爬取然后添加进数据库
                List<ChapterPic> chapterPics = CrawOneLink.getAllPicsByLink(chapterLink, cookie, username, password);

                //将图片批量存入数据库
                if (chapterPics.size() > 0) {
                    novelDao.insertChapterPicBatch(chapterPics);
                }

                //将图片按照顺序保存至本地
                //CrawlUtil.savePicToBase(novelName, chapterName, chapterPics, picSavePath, novelDao);
            }
        }

        return null;
    }

    @Override
    public void crawlonelManhuLinks(String links) {
        insertOrUpdateOneNovel(links);
    }

    @Override
    @Transactional
    public void insertOrUpdateOneNovel(String manhuaLink) {

        String ss[] = manhuaLink.split("/");
        String novelId = ss[ss.length - 1].replace(".html", "");

        Novel p = new Novel();
        p.setId(novelId);
        List<Novel> existsNovel = novelDao.selectNovelByNovelId(p);
        if (existsNovel.size() > 0) {
            System.out.print("该漫画已经爬到了..." + manhuaLink);
            Novel novel = CrawOneLink.getNovelDetailByUrl(manhuaLink);
            Novel exts = existsNovel.get(0);

            //如果更新时间不变，则不必再继续爬取了
            if (novel.getYeMianDate().equals(exts.getYeMianDate())) {
                return;
            } else {
                //表示已经更新了，则更新漫画的更新时间
                novelDao.updateNovel(novel);

                List<Novel> no = novelDao.selectNovelChapterAdnPics(novel);

                //爬取出现有的所有的章节信息
                List<Chapter> chapters = crawlAllChapterLinksById(manhuaLink);
                //如果当前章节不存在，则爬取之后入库
                if (no.size() == 0 || no.get(0).getChapter().size() == 0) {
                    //插入漫画的章节信息
                    if (chapters != null && chapters.size() > 0) {
                        System.out.print("漫画：" + novel.getName() + ", 没有更新，不必更新了");
                        novelDao.insertChapterBatch(chapters);
                    }
                } else {
                    //如果存在部分，则找出不存在的章节入库
                    List<Chapter> insertChapters = new ArrayList<>();
                    List<Chapter> baseChapters = no.get(0).getChapter();
                    for (Chapter current: chapters) {
                        boolean insert = true;
                        for (Chapter exscah: baseChapters) {
                            if (current.getId().equals(exscah.getId())) {
                                insert = false;
                                break;
                            }
                        }
                        if (insert) {
                            insertChapters.add(current);
                        }
                    }
                    //插入更新的章节
                    if (insertChapters.size() > 0) {
                        novelDao.insertChapterBatch(insertChapters);
                    }

                    if (insertChapters.size() > 0) {
                        for (Chapter chapter: insertChapters) {
                            //不存在继续爬取然后添加进数据库
                            List<ChapterPic> chapterPics = CrawOneLink.getAllPicsByLink(chapter.getChapterUrl(), cookie, username, password);

                            //将图片批量存入数据库
                            novelDao.insertChapterPicBatch(chapterPics);

                            //将图片按照顺序保存至本地
                            //CrawlUtil.savePicToBase(novel.getName(), chapter.getChapterName(), chapterPics, picSavePath, novelDao);
                        }
                    }
                }

                //继续检查所有的章节是否已经下载至本地
                for(Chapter chapter: chapters) {
                    //不存在继续爬取然后添加进数据库
                    List<ChapterPic> chapterPics = CrawOneLink.getAllPicsByLink(chapter.getChapterUrl(), cookie, username, password);

                    //未下载的图片, 将图片按照顺序保存至本地
                    ChapterPic noDown = new ChapterPic(chapter.getId(), Constants.NoDownToLocal);
                    List<ChapterPic> noDownChapterPics = novelDao.selectPicsByChapterId(noDown);
                    //CrawlUtil.savePicToBase(novel.getName(), chapter.getChapterName(), noDownChapterPics, picSavePath, novelDao);

                    ChapterPic down = new ChapterPic(chapter.getId(), Constants.DownToLocal);
                    List<ChapterPic> exsisChapterPics = novelDao.selectPicsByChapterId(down);

                    List<ChapterPic> inertChapterPics = new ArrayList<>();
                    //如果图片和下载的图片不相等则更新图片至本地
                    if (chapterPics.size() != exsisChapterPics.size()) {
                        for (ChapterPic c1: chapterPics) {

                            boolean insert = true;

                            for (ChapterPic c2: exsisChapterPics) {
                                if ("1".equals(c1.getIsDownToLocal()) && c1.getIsDownToLocal().equals(c2.getIsDownToLocal())) {
                                    insert = false;
                                    break;
                                }
                            }
                            if (insert) {
                                inertChapterPics.add(c1);
                            }
                        }
                    }
                    //CrawlUtil.savePicToBase(novel.getName(), chapter.getChapterName(), inertChapterPics, picSavePath, novelDao);
                }

            }
            return;
        }

        //插入漫画基本信息
        Novel novel = CrawOneLink.getNovelDetailByUrl(manhuaLink);
        novelDao.insertNovel(novel);

        //插入漫画的章节信息
        List<Chapter> chapters = crawlAllChapterLinksById(manhuaLink);

        if (chapters == null || chapters.size() == 0) {
            return;
        }
        novelDao.insertChapterBatch(chapters);

        //插入漫画的图片信息
        List<Novel> novels = new ArrayList<>();
        novels.add(novel);
        novel.setChapter(chapters);
        crawlPicssByChapterLink(novels);
    }

    /**
     * 根据漫画链接爬取漫画的基本信息
     * @return
     */
    @Override
    public Novel crawOneNovelDeatilByLink(String manhuaLink) {
        Novel novel = CrawOneLink.getNovelDetailByUrl(manhuaLink);
        return novel;
    }

    /**
     * 根据漫画Id爬取所有的章节链接
     * @param manhuaLink
     * @return
     */
    @Override
    public List<Chapter> crawlAllChapterLinksById(String manhuaLink) {
        String[] spls = manhuaLink.split("/");
        String novelId = spls[spls.length - 1].replace(".html", "");

        String url = "https://www.qiteman.com/index.php/api/comic/chapter";
        HttpClient client = new HttpClient();
        PostMethod postMethod = new PostMethod(url);

        //添加请求头
        postMethod.addRequestHeader("User-Agent", CrawlUtil.getUserAgent());
        postMethod.addRequestHeader("content-type", "application/x-www-form-urlencoded; charset=UTF-8");

        //添加请求参数
        postMethod.addParameter("mid", novelId);

        List<Chapter> chapters = new ArrayList<>();
        try {
            client.executeMethod(postMethod);
            String res = postMethod.getResponseBodyAsString();
            JSONArray data = JSONArray.parseArray(JSONObject.parseObject(res).getString("data"));
            for (int i = 0; i < data.size(); i++) {
                JSONObject one = (JSONObject) data.get(i);
                String chapterId = one.getString("id");
                Date createDate = new Date();
                Date updateDate = new Date();
                String chapterName = one.getString("name");
                String chapterUrl = Constants.domain + one.getString("link");
                String vip = one.getString("vip");
                Chapter chapter = new Chapter(
                        chapterId, createDate, updateDate, chapterName, chapterUrl, novelId, vip
                );
                chapter.toString();
                chapters.add(chapter);
                System.out.print(chapter);
            }
        } catch (IOException e) {
            System.out.print("爬取小说：" + novelId + "，失败");
        }
        try {
            Thread.sleep(Constants.sleepSeconds);
        } catch (InterruptedException e) {
            System.out.print("每次请求之后，睡眠几秒，防止被针对");
        }finally {
            postMethod.releaseConnection();
        }
        return chapters;
    }

    /**
     * 获取所有的章节的图片, 注意此处需要判断VIP
     * @param chapterLink
     * @return
     */
    @Override
    public List<ChapterPic> crawlPicsByChaperLink(String chapterLink) {
        List<ChapterPic> chapterPics = CrawOneLink.getAllPicsByLink(chapterLink, cookie, username, password);
        return chapterPics;
    }

    /**
     * 查找所有的漫画，章节，以及图片
     * @param novel
     * @return
     */
    @Override
    public List<Novel> selectNovelChapterAdnPics(Novel novel) {
        List<Novel> novels = novelDao.selectNovelChapterAdnPics(novel);
        return novels;
    }

    public static void main(String[] args) {
        new ManhuaSpiderServiceImpl().crawlAllManhuLinks();
    }
}
